﻿using HtmlAgilityPack;
using Manhua3.Common;
using Manhua3.SQLiteTable;
using SharpCompress.Compressor;
using SharpCompress.Compressor.Deflate;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Manhua3.Helper;
using Manhua3.Client;
namespace Manhua3.Provider
{
    public class DM4399Provider : IComicProvider
    {
        private static DateTime lastUpdatedTime = DateTime.MinValue;

        private const string latest_url = "http://dm.4399.com/mh/";
        private const string base_url = "http://dm.4399.com";
        private const string search_url = "http://dm.4399.com/search/mh_cata_search.php?sw=";
        private const string provider = "4399";

        public int TopCount { get { return 25; } }
        public string ProviderName
        {
            get { return provider; }
        }

        public async Task SaveLatestComicsAsync(bool cache)
        {
            if (cache)
            {
                if ((DateTime.Now - lastUpdatedTime).TotalMinutes < 10)
                {
                    return;
                }
            }

            lastUpdatedTime = DateTime.Now;

            using (DbContext context = new DbContext())
            {
                context.BeginTransaction();

                try
                {
                    HtmlDocument html = await XHttpClient.GetHtmlDocumentAsync(latest_url);

                    var ul = HtmlHelper.GetElementByClass(html.DocumentNode, "x_list clearfix").FirstOrDefault();
                    var lis = ul.Elements("li").Reverse();
                    foreach (var li in lis)
                    {
                        var a = li.Elements("a").ToList();
                        var comic = await context.GetComic(a[0].InnerText, this.ProviderName);
                        if (comic == null)
                        {
                            comic = new SQLiteComic()
                            {
                                Provider = provider,
                                Title = a[0].InnerText,
                                ChapterUrl = base_url + a[0].Attributes["href"].Value
                            };

                            await context.InsertAsync(comic);
                        }

                        try
                        {
                            DateTime time;
                            if (!DateTime.TryParse(li.Element("span").InnerText, out time))
                                time = DateTime.Now;
                            await context.InsertChapter(
                                a[1].InnerText.Trim('[', ' ', ']'),
                                comic.Id,
                                time);

                            if (string.IsNullOrEmpty(comic.CoverUrl))
                            {
                                await this.UpdateComic(context, comic, true);
                            }

                            // 读取封面 所有章节
                            // await this.UpdateComic(context, comic);
                        }
                        catch
                        {
                        }
                    }

                    context.Commit();
                }
                catch
                {
                    context.Rollback();
                    throw;
                }
            }
        }

        public async Task SavePagesAsync(int chapterId)
        {
            using (DbContext context = new DbContext())
            {
                var chapter = await context.GetAsync<SQLiteChapter>(chapterId);
                if (chapter == null)
                    throw new ArgumentNullException("章节不存在");

                context.BeginTransaction();

                try
                {
                    HtmlDocument html = await XHttpClient.GetHtmlDocumentAsync(chapter.Url);

                    var document = html.DocumentNode.InnerHtml;

                    // picdir  = 'http://dmimg.5054399.com/mh/haizeiwang/694u/';
                    // var pic_count = 16,

                    var match = Regex.Match(document, @"(?<=var pic_count = )\d+");
                    chapter.TotalPage = int.Parse(match.Value);

                    match = Regex.Match(document, @"picdir  = '.*';");
                    string dir = match.Value;
                    dir = dir.Substring(dir.IndexOf('\'') + 1);
                    dir = dir.Remove(dir.LastIndexOf('\''));

                    for (int i = 1; i <= chapter.TotalPage; i++)
                    {
                        SQLitePage page = new SQLitePage()
                        {
                            Page = i,
                            Url = dir + i.ToString("D3") + ".jpg",
                            ChapterId = chapter.Id
                        };

                        await context.InsertAsync(page);
                    }

                    await context.UpdateAsync(chapter);

                    context.Commit();
                }
                catch
                {
                    context.Rollback();
                    throw;
                }
            }
        }

        public async Task SaveChaptersAsync(int comicId)
        {
            using (DbContext context = new DbContext())
            {
                context.BeginTransaction();

                try
                {
                    var comic = await context.GetAsync<SQLiteComic>(comicId);
                    if (comic != null)
                    {
                        await this.UpdateComic(context, comic);
                    }

                    context.Commit();
                }
                catch
                {
                    context.Rollback();
                    throw;
                }
            }
        }

        private async Task UpdateComic(DbContext context, SQLiteComic comic, bool onlyCover = false)
        {
            HtmlDocument html = await XHttpClient.GetHtmlDocumentAsync(comic.ChapterUrl);

            // 读取封面
            var g_cover = HtmlHelper.GetElementByClass(html.DocumentNode, "g_cover").FirstOrDefault();
            if (g_cover != null)
            {
                comic.CoverUrl = g_cover.ChildNodes[1].Attributes["src"].Value;
            }

            // 读取作者，类型
            var g_coverinfo = HtmlHelper.GetElementByClass(html.DocumentNode, "g_coverinfo").FirstOrDefault();
            if (g_coverinfo != null)
            {
                comic.Author = g_coverinfo.ChildNodes[1].ChildNodes[1].InnerText;
                comic.Type = g_coverinfo.ChildNodes[5].ChildNodes[1].InnerText;
            }

            await context.UpdateAsync(comic);

            if (onlyCover) return;

            // dmlink 读取所有章节
            var dmlink = html.GetElementbyId("dmlink");
            var lis = dmlink.ChildNodes.Reverse();

            foreach (var li in lis)
            {
                if (li.ChildNodes.Count == 0) continue;

                var title = li.ChildNodes[0].InnerText;
                var chapter = await context.GetChapter(title, comic.Id);
                if (chapter == null)
                {
                    chapter = new SQLiteChapter()
                    {
                        ComicId = comic.Id,
                        Title = title,
                        Url = base_url + li.ChildNodes[0].Attributes["href"].Value,
                        TotalPage = 0,
                        Updated = new DateTime(1970, 1, 1),
                    };

                    await context.InsertAsync(chapter);
                }
                else if(string.IsNullOrEmpty(chapter.Url))
                {
                    chapter.Url = base_url + li.ChildNodes[0].Attributes["href"].Value;
                    await context.UpdateAsync(chapter);
                }
            }
        }

        public override string ToString()
        {
            return provider;
        }
    }
}
